#include "DeviceClass.h"

DeviceClass::DeviceClass(bool f,bool v)
	:Component(COMP_DEVICE),
#ifdef _DEBUG
	m_infoQueue(NULL),
	m_debug(NULL),
#endif // _DEBUG
	m_device(NULL),
	m_swapChain(NULL),
	m_fullScreen(f),
	m_vsyncEnable(v),
	m_screenHeight(0),
	m_screenWidth(0),
	m_deviceInfo(),
	m_activateModelDesc()
{
	ZeroMemory(&m_deviceInfo,sizeof(m_deviceInfo));
	m_dumpFile.open(DEVICE_DUMP_FILENAME,fstream::trunc|fstream::out);
	if(!m_dumpFile.is_open())
	{
		EXCEPTION("Can not open dump file.")
	}
}

DeviceClass::~DeviceClass(void)
{
#ifdef _DEBUG
	if(m_debug)
	{
		m_debug->Release();
		m_debug=0;
	}
	
	if(m_infoQueue)
	{
		m_infoQueue->Release();
		m_infoQueue=0;
	}
#endif
	m_dumpFile.close();

	if(m_device)
	{
		m_device->Release();
		m_device=0;
	}



}

void DeviceClass::AddedToObject()
{
	RequestMessage(MSG_INITIAL_GRAPHICS,&DeviceClass::Initialize);
	RequestMessage(MSG_CREATE_BUFFER,&DeviceClass::CreateBuffer);
	RequestMessage(MSG_CREATE_DEPTH_STENCIL_STATE,&DeviceClass::CreateDepthStencilState);
	RequestMessage(MSG_CREATE_INPUT_LAYOUT,&DeviceClass::CreateInputLayout);
	RequestMessage(MSG_CREATE_PIXEL_SHADER,&DeviceClass::CreatePixelShader);
	RequestMessage(MSG_CREATE_VERTEX_SHADER,&DeviceClass::CreateVertexShader);
	RequestMessage(MSG_CREATE_RASTERIZER_STATE,&DeviceClass::CreateRasterizerState);
	RequestMessage(MSG_CREATE_TEXTURE1D,&DeviceClass::CreateTexture1D);
	RequestMessage(MSG_CREATE_TEXTURE2D,&DeviceClass::CreateTexture2D);
	RequestMessage(MSG_CREATE_TEXTURE3D,&DeviceClass::CreateTexture3D);
	RequestMessage(MSG_CREATE_TEXTURE,&DeviceClass::CreateTexture);
	RequestMessage(MSG_COMPARE_SHARED,&DeviceClass::CompileShaderFromFile);
	RequestMessage(MSG_DUMP_ALL_MESSAGE,&DeviceClass::DumpAllMessage);
	RequestMessage(MSG_PRESENT,&DeviceClass::Present);
	RequestMessage(MSG_CREATE_EFFECT,&DeviceClass::CreateEffect);
	RequestMessage(MSG_CREATE_SAMPLER,&DeviceClass::CreateSamplerState);
}

ID3D11Device* DeviceClass::GetDevice() const
{
	return m_device;
}

bool DeviceClass::GetDeviceInfo()
{

	IDXGIFactory* pFactory;
	IDXGIAdapter* pAdapter;
	IDXGIOutput* pOutput;
	unsigned int numModes=0;
	DXGI_MODE_DESC* displayModeList;
	DXGI_ADAPTER_DESC adapter_Desc;
	
	HRESULT hr = CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)(&pFactory) );
	if(FAILED(hr))
		EXCEPTION("CreateDXGIFactory FAILED")
		
	// Use the factory to create an adapter for the primary graphics interface (video card).
	hr = pFactory->EnumAdapters(0, &pAdapter);
	if(FAILED(hr))
	{
		EXCEPTION("EnumAdapters FAILED")
	}

	// Enumerate the primary adapter output (monitor).
	hr = pAdapter->EnumOutputs(0, &pOutput);
	if(FAILED(hr))
	{
		EXCEPTION("EnumOutputs FAILED")
	}

	// Get the number of modes that fit the DXGI_FORMAT_R8G8B8A8_UNORM display format for the adapter output (monitor).
	hr = pOutput->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &numModes, NULL);
	if(FAILED(hr))
	{
		EXCEPTION("GetDisplayModeList FAILED")
	}

	// Create a list to hold all the possible display modes for this monitor/video card combination.
	displayModeList = new DXGI_MODE_DESC[numModes];
	
	// Now fill the display mode list structures.
	hr = pOutput->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &numModes, displayModeList);
	if(FAILED(hr))
	{
		EXCEPTION("GetDisplayModeList FAILED")
	}

	//m_deviceInfo.m_descriptions.insert(m_deviceInfo.m_descriptions.begin(),&displayModeList[0],&displayModeList[numModes-1]);
	
	pAdapter->GetDesc(&m_deviceInfo.adapterDesc);

	for(unsigned int i=0; i<numModes; i++)
	{
		if(displayModeList[i].Width == m_screenWidth)
		{
			if(displayModeList[i].Height == m_screenHeight)
			{
				m_activateModelDesc=displayModeList[i];
			}
		}
	}
	
	// Release the display mode list.
	delete [] displayModeList;
	displayModeList = 0;

	// Release the adapter output.
	pOutput->Release();
	pOutput = 0;

	// Release the adapter.
	pAdapter->Release();
	pAdapter = 0;

	// Release the factory.
	pFactory->Release();
	pFactory = 0;
	return true;
}

unsigned int DeviceClass::GetScreenWidth() const
{
	return m_screenWidth;
}


unsigned int DeviceClass::GetScreenHeight() const
{
	return m_screenHeight;
}

bool DeviceClass::InitialDevice(HWND hwnd)
{
	HRESULT hr=0;
	UINT createDeviceFlags = 0;	
	ID3D11DeviceContext* deviceContext=NULL;
	ID3D11RenderTargetView* defaultRenderTargetView=NULL;
	D3D11_TEXTURE2D_DESC depthBufferDesc;
	D3D11_DEPTH_STENCIL_DESC depthStencilDesc;
	D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc;
	ID3D11Texture2D* defaultDepthStencilBuffer=NULL;
	ID3D11DepthStencilState* defaultDepthStencilState=NULL;
	ID3D11DepthStencilView* defaultDepthStencilView=NULL;
	ID3D11RasterizerState* defaultRasterState=NULL;
	D3D11_RASTERIZER_DESC rasterDesc;
	
#ifdef _DEBUG
    createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif

    D3D_DRIVER_TYPE driverTypes[] =
    {
        D3D_DRIVER_TYPE_HARDWARE,
        D3D_DRIVER_TYPE_WARP,
        D3D_DRIVER_TYPE_REFERENCE,
    };
    UINT numDriverTypes = ARRAYSIZE( driverTypes );

    D3D_FEATURE_LEVEL featureLevels[] =
    {
        D3D_FEATURE_LEVEL_11_0,
        D3D_FEATURE_LEVEL_10_1,
        D3D_FEATURE_LEVEL_10_0,
    };
	UINT numFeatureLevels = ARRAYSIZE( featureLevels );

	if(m_screenWidth==0||m_screenHeight==0)
		EXCEPTION("Screen width/height not init")
		
    DXGI_SWAP_CHAIN_DESC sd;
    ZeroMemory( &sd, sizeof( sd ) );
    sd.BufferCount = 1;
	sd.BufferDesc.Width = m_screenWidth;
	sd.BufferDesc.Height = m_screenHeight;
    sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
	
	if(m_vsyncEnable)
	{
	    sd.BufferDesc.RefreshRate.Numerator = m_activateModelDesc.RefreshRate.Numerator;
		sd.BufferDesc.RefreshRate.Denominator = m_activateModelDesc.RefreshRate.Denominator;
	}
	else
	{
	    sd.BufferDesc.RefreshRate.Numerator = 60;
		sd.BufferDesc.RefreshRate.Denominator = 1;
	}
	
    sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    sd.OutputWindow = hwnd;
    sd.SampleDesc.Count = 1;
    sd.SampleDesc.Quality = 0;
	sd.Windowed=!m_fullScreen;		
	
    for( UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++ )
    {
        hr = D3D11CreateDeviceAndSwapChain( NULL, driverTypes[driverTypeIndex], NULL, createDeviceFlags, featureLevels, numFeatureLevels,
			D3D11_SDK_VERSION, &sd, &m_swapChain, &m_device, &m_feature, &deviceContext );
        if( SUCCEEDED( hr ) )
            break;
    }

	CHECK_FAILED(hr)
	
#ifdef _DEBUG
	CreateInfoQueue();
#endif // _DEBUG

	ID3D11Texture2D* backBufferPtr=NULL;

	// Get the pointer to the back buffer.
	hr = m_swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&backBufferPtr);
	CHECK_FAILED(hr)

	hr = m_device->CreateRenderTargetView(backBufferPtr, NULL, &defaultRenderTargetView);

	CHECK_FAILED(hr)

	backBufferPtr->Release();
	backBufferPtr = 0;

	// Initialize the description of the depth buffer.
	ZeroMemory(&depthBufferDesc, sizeof(depthBufferDesc));

	// Set up the description of the depth buffer.

	depthBufferDesc.Width = m_screenWidth;
	depthBufferDesc.Height = m_screenHeight;
	depthBufferDesc.MipLevels = 1;
	depthBufferDesc.ArraySize = 1;
	depthBufferDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
	depthBufferDesc.SampleDesc.Count = 1;
	depthBufferDesc.SampleDesc.Quality = 0;
	depthBufferDesc.Usage = D3D11_USAGE_DEFAULT;
	depthBufferDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
	depthBufferDesc.CPUAccessFlags = 0;
	depthBufferDesc.MiscFlags = 0;

	// Create the texture for the depth buffer using the filled out description.
	hr = m_device->CreateTexture2D(&depthBufferDesc, NULL, &defaultDepthStencilBuffer);
	CHECK_FAILED(hr)

	// Initialize the description of the stencil state.
	ZeroMemory(&depthStencilDesc, sizeof(depthStencilDesc));

	// Set up the description of the stencil state.
	depthStencilDesc.DepthEnable = true;
	depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
	depthStencilDesc.DepthFunc = D3D11_COMPARISON_LESS;

	depthStencilDesc.StencilEnable = true;
	depthStencilDesc.StencilReadMask = 0xFF;
	depthStencilDesc.StencilWriteMask = 0xFF;

	// Stencil operations if pixel is front-facing.
	depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
	depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
	depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
	depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;

	// Stencil operations if pixel is back-facing.
	depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
	depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
	depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
	depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;

	// Create the depth stencil state.
	hr = m_device->CreateDepthStencilState(&depthStencilDesc, &defaultDepthStencilState);
	CHECK_FAILED(hr)
	
	//deviceContext->OMSetDepthStencilState(defaultDepthStencilState, 1);

	// Initialize the depth stencil view.
	ZeroMemory(&depthStencilViewDesc, sizeof(depthStencilViewDesc));

	// Set up the depth stencil view description.
	depthStencilViewDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
	depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
	depthStencilViewDesc.Texture2D.MipSlice = 0;

	// Create the depth stencil view.
	hr = m_device->CreateDepthStencilView(defaultDepthStencilBuffer, &depthStencilViewDesc, &defaultDepthStencilView);
	CHECK_FAILED(hr)

	deviceContext->OMSetRenderTargets(1, &defaultRenderTargetView, NULL);

	// Setup the raster description which will determine how and what polygons will be drawn.
	rasterDesc.AntialiasedLineEnable = false;
	rasterDesc.CullMode = D3D11_CULL_BACK;
	rasterDesc.DepthBias = 0;
	rasterDesc.DepthBiasClamp = 0.0f;
	rasterDesc.DepthClipEnable = false;
	rasterDesc.FillMode = D3D11_FILL_SOLID;
	rasterDesc.FrontCounterClockwise = false;
	rasterDesc.MultisampleEnable = false;
	rasterDesc.ScissorEnable = false;
	rasterDesc.SlopeScaledDepthBias = 0.0f;

	// Create the rasterizer state from the description we just filled out.
	hr = m_device->CreateRasterizerState(&rasterDesc, &defaultRasterState);
	CHECK_FAILED(hr)

	deviceContext->RSSetState(defaultRasterState);


	D3D11_VIEWPORT vp;
	vp.Width = (float)m_screenWidth;
	vp.Height = (float)m_screenHeight;
    vp.MinDepth = 0.0f;
    vp.MaxDepth = 1.0f;
    vp.TopLeftX = 0.0f;
    vp.TopLeftY = 0.0f;
	deviceContext->RSSetViewports( 1, &vp );

	m_deviceContext=boost::make_shared<DeviceContext>(
		deviceContext,
		defaultRenderTargetView,
		defaultDepthStencilBuffer,
		defaultDepthStencilState,
		defaultDepthStencilView,
		defaultRasterState,
		this);
	AddLocalComponent(m_deviceContext);

	return true;
}

void DeviceClass::CreateTexture(const Message& msg)
{
	if(m_device==NULL)
		EXCEPTION("")
	string path;
	ID3D11ShaderResourceView** tempView=NULL;
	AuxUnGroupArgus(msg.p,path,tempView);
	HRESULT hr=D3DX11CreateShaderResourceViewFromFile(m_device,path.c_str(),NULL,NULL,tempView,NULL);
	CHECK_FAILED(hr)
}

void DeviceClass::CreateInfoQueue()
{
	HRESULT hr=S_OK;
	if(m_device==NULL)
		EXCEPTION("Device not created")
		
	hr=m_device->QueryInterface(__uuidof(ID3D11Debug),(LPVOID*)&m_debug);
	if(FAILED(hr))
		EXCEPTION("Create ID3D11Debug failed")

	hr=m_debug->ReportLiveDeviceObjects(D3D11_RLDO_DETAIL);
	if(FAILED(hr))
		EXCEPTION("Set ReportLiveDeviceObjects failed")

	hr=m_device->QueryInterface(__uuidof(ID3D11InfoQueue),(LPVOID*)&m_infoQueue);
	if(FAILED(hr))
		EXCEPTION("Create ID3D11InfoQueue failed")

	m_infoQueue->ClearStoredMessages();
	m_infoQueue->ClearRetrievalFilter();
	m_infoQueue->ClearStorageFilter();

	D3D11_INFO_QUEUE_FILTER filter;
	ZeroMemory(&filter, sizeof(D3D11_INFO_QUEUE_FILTER));
	D3D11_MESSAGE_SEVERITY severity;
	severity=D3D11_MESSAGE_SEVERITY_ERROR;
	filter.DenyList.NumSeverities=1;
	filter.DenyList.pSeverityList=&severity;
	m_infoQueue->AddStorageFilterEntries(&filter);
	m_infoQueue->AddRetrievalFilterEntries(&filter);
}

void DeviceClass::Initialize(const Message& msg)
{
	int sw,sh;
	HWND hwnd;
	HINSTANCE hInstance;
	AuxUnGroupArgus(msg.p,hInstance,hwnd,sw,sh);
	m_screenHeight=sh;
	m_screenWidth=sw;
	try
	{
		GetDeviceInfo();
		InitialDevice(hwnd);
	}
	catch(std::exception& e)
	{
		PRINT_ERROR(e);
	}
}

bool DeviceClass::CheckFeatures()
{
	D3D11_FEATURE_DATA_THREADING threadingFeature;
	m_device->CheckFeatureSupport(D3D11_FEATURE_THREADING,&threadingFeature,sizeof(threadingFeature));
	return true;
}

#ifdef _DEBUG
void DeviceClass::DumpAllMessage(const Message& msg)
{
	if(!m_dumpFile.is_open())
	{
		EXCEPTION("Dump file not open")
	}
	UINT64 numStoredMessages = m_infoQueue->GetNumStoredMessages();
	for (UINT64 i = 0 ; i < numStoredMessages ; i++ )
	{
		// Get the size of the message
		SIZE_T messageLength = 0;
		m_infoQueue->GetMessage(i, NULL, &messageLength);
		// Allocate space and get the message
		D3D11_MESSAGE * pMessage = (D3D11_MESSAGE*)malloc(messageLength);
		m_infoQueue->GetMessage(i, pMessage, &messageLength);
		m_dumpFile<<pMessage->pDescription<<endl;
		free(pMessage);
	}
}

string DeviceClass::DetectError()
{
	stringstream ss;
	if(!m_infoQueue)
	{
		EXCEPTION("ID3D11InfoQueue not created!")
	}

	UINT64 numStoredMessages = m_infoQueue->GetNumStoredMessages();
	for (UINT64 i = 0 ; i < numStoredMessages ; i++ )
	{
		// Get the size of the message
		SIZE_T messageLength = 0;
		m_infoQueue->GetMessage(i, NULL, &messageLength);
		// Allocate space and get the message
		D3D11_MESSAGE * pMessage = (D3D11_MESSAGE*)malloc(messageLength);
		m_infoQueue->GetMessage(i, pMessage, &messageLength);
		if(pMessage==NULL)
			EXCEPTION("")
		if((pMessage)->Severity==D3D11_MESSAGE_SEVERITY_ERROR)
		{
			ss<<pMessage->pDescription<<endl;
		}
		free(pMessage);
	}
	
	m_infoQueue->ClearStoredMessages();
	return ss.str();
}

#endif // _DEBUG

void DeviceClass::CreateSamplerState(const Message& msg)
{
	try
	{
		D3D11_SAMPLER_DESC* samplerDesc=NULL;
		ID3D11SamplerState** samplerState=NULL;
		AuxUnGroupArgus(msg.p,samplerDesc,samplerState);
		HRESULT hr=m_device->CreateSamplerState(samplerDesc,samplerState);
		CHECK_FAILED(hr)
	}
	catch(DX11Exception& e)
	{
		PRINT_ERROR(e)
	}
}

void DeviceClass::CreateBuffer(const Message& msg)
{
	try
	{
		D3D11_BUFFER_DESC* bufferDesc=NULL;
		D3D11_SUBRESOURCE_DATA* initData=NULL;
		ID3D11Buffer** pBuffer=NULL;
		AuxUnGroupArgus(msg.p,bufferDesc,initData,pBuffer);
		HRESULT hr=m_device->CreateBuffer(bufferDesc,initData,pBuffer);
		CHECK_FAILED(hr)
		
	}
	catch(DX11Exception& e)
	{
		PRINT_ERROR(e)
	}
}

void DeviceClass::CreateDepthStencilState(const Message& msg)
{
	try
	{
		D3D11_DEPTH_STENCIL_DESC* depthDesc=NULL;
		ID3D11DepthStencilState** pDepthStencilState=NULL;
		AuxUnGroupArgus(msg.p,depthDesc,pDepthStencilState);
		HRESULT hr=m_device->CreateDepthStencilState(depthDesc,pDepthStencilState);
		CHECK_FAILED(hr)
		
	}
	catch(DX11Exception& e)
	{
		PRINT_ERROR(e)
	}
}

void DeviceClass::CreateInputLayout(const Message& msg)
{
	try
	{
		boost::shared_ptr<Vector<D3D11_INPUT_ELEMENT_DESC>> inputDescPtr;
		D3DX11_EFFECT_SHADER_DESC effectDesc;
		ID3D11InputLayout** pInputLayout=NULL;
		AuxUnGroupArgus(msg.p,inputDescPtr,effectDesc,pInputLayout);
		HRESULT hr=m_device->CreateInputLayout(&((*inputDescPtr)[0]),inputDescPtr->size(),effectDesc.pBytecode,effectDesc.BytecodeLength,pInputLayout);
		CHECK_FAILED(hr)
		
	}
	catch(DX11Exception& e)
	{
		PRINT_ERROR(e)
	}
}

void DeviceClass::CreateEffect(const Message& msg)
{
	try
	{
		string szFileName;
		Effect::sPtr* tmpEffect=NULL;
		ID3DX11Effect* effect=NULL;
		ID3DBlob* effectCode=NULL;
		AuxUnGroupArgus(msg.p,szFileName,tmpEffect);
		CompileShaderFromFile(szFileName,"","fx_5_0",&effectCode);
		HRESULT hr=D3DX11CreateEffectFromMemory(effectCode->GetBufferPointer(),effectCode->GetBufferSize(),0,m_device,&effect);
		CHECK_FAILED(hr)
		*tmpEffect=boost::make_shared<Effect>(effect);
		AddLocalComponent(*tmpEffect);
		}
	catch(std::exception& e)
	{
		PRINT_ERROR(e)
	}
}

void DeviceClass::CreateVertexShader(const Message& msg)
{
	try
	{
		ID3DBlob* vertexShaderCode=NULL;
		ID3D11VertexShader** pVexterShader=NULL;
		AuxUnGroupArgus(msg.p,vertexShaderCode,pVexterShader);
		HRESULT hr=m_device->CreateVertexShader(vertexShaderCode->GetBufferPointer(),vertexShaderCode->GetBufferSize(),NULL,pVexterShader);
		CHECK_FAILED(hr)
		
	}
	catch(DX11Exception& e)
	{
		PRINT_ERROR(e)
	}
}

void DeviceClass::CreatePixelShader(const Message& msg)
{
	try
	{
		ID3DBlob* pixelShaderCode=NULL;
		ID3D11PixelShader** pPixelShader=NULL;
		AuxUnGroupArgus(msg.p,pixelShaderCode,pPixelShader);
		HRESULT hr=m_device->CreatePixelShader(pixelShaderCode->GetBufferPointer(),pixelShaderCode->GetBufferSize(),NULL,pPixelShader);
		CHECK_FAILED(hr)
		
	}
	catch(DX11Exception& e)
	{
		PRINT_ERROR(e)
	}
}

void DeviceClass::CreateRasterizerState(const Message& msg)
{
	try
	{
		D3D11_RASTERIZER_DESC* rasterizerDesc=NULL;
		ID3D11RasterizerState** pRasterizerState=NULL;
		AuxUnGroupArgus(msg.p,rasterizerDesc,pRasterizerState);
		HRESULT hr=m_device->CreateRasterizerState(rasterizerDesc,pRasterizerState);
		CHECK_FAILED(hr)
		
	}
	catch(DX11Exception& e)
	{
		PRINT_ERROR(e)
	}
}

void DeviceClass::CreateTexture1D(const Message& msg)
{
	try
	{
		D3D11_TEXTURE1D_DESC* textureDesc=NULL;
		D3D11_SUBRESOURCE_DATA* initData=NULL;
		ID3D11Texture1D** pTexture1D=NULL;
		AuxUnGroupArgus(msg.p,textureDesc,initData,pTexture1D);
		HRESULT hr=m_device->CreateTexture1D(textureDesc,initData,pTexture1D);
		CHECK_FAILED(hr)
		
	}
	catch(DX11Exception& e)
	{
		PRINT_ERROR(e)
	}
}

void DeviceClass::CreateTexture2D(const Message& msg)
{
	try
	{
		D3D11_TEXTURE2D_DESC* textureDesc=NULL;
		D3D11_SUBRESOURCE_DATA* initData=NULL;
		ID3D11Texture2D** pTexture2D=NULL;
		AuxUnGroupArgus(msg.p,textureDesc,initData,pTexture2D);
		HRESULT hr=m_device->CreateTexture2D(textureDesc,initData,pTexture2D);
		CHECK_FAILED(hr)
		
	}
	catch(DX11Exception& e)
	{
		PRINT_ERROR(e)
	}	
}

void DeviceClass::CreateTexture3D(const Message& msg)
{
	try
	{
		D3D11_TEXTURE3D_DESC* textureDesc=NULL;
		D3D11_SUBRESOURCE_DATA* initData=NULL;
		ID3D11Texture3D** pTexture3D=NULL;
		AuxUnGroupArgus(msg.p,textureDesc,initData,pTexture3D);
		HRESULT hr=m_device->CreateTexture3D(textureDesc,initData,pTexture3D);
		CHECK_FAILED(hr)
		
	}
	catch(DX11Exception& e)
	{
		PRINT_ERROR(e)
	}
	
}

void DeviceClass::Present(const Message& msg)
{
	try
	{
		if(m_vsyncEnable)
			m_swapChain->Present(1,0);
		else
			m_swapChain->Present(0,0);
	}
	catch(std::exception& e)
	{
		PRINT_ERROR(e)
	}
}

void DeviceClass::CompileShaderFromFile(string szFileName, string szEntryPoint, string szShaderModel,ID3DBlob** blobOut )
{
		HRESULT hr = S_OK;
	
		DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS;
#if defined( DEBUG ) || defined( _DEBUG )
    // Set the D3DCOMPILE_DEBUG flag to embed debug information in the shaders.
    // Setting this flag improves the shader debugging experience, but still allows 
    // the shaders to be optimized and to run exactly the way they will run in 
    // the release configuration of this program.
    dwShaderFlags |= D3DCOMPILE_DEBUG;
#endif

		ID3DBlob* pErrorBlob=NULL;
		hr = D3DX11CompileFromFile( szFileName.c_str(), NULL, NULL, szEntryPoint.c_str(), szShaderModel.c_str(), 
			dwShaderFlags, 0, NULL, blobOut, &pErrorBlob, NULL );
		char* str=NULL;
		if(pErrorBlob!=NULL)
		{
			str=(char*)pErrorBlob->GetBufferPointer();
			EXCEPTION(str);
		}
		
}

//--------------------------------------------------------------------------------------
// Helper for compiling shaders with D3DX11
//--------------------------------------------------------------------------------------
void DeviceClass::CompileShaderFromFile(const Message& msg)
{
	try
	{
		string szFileName;
		string szEntryPoint;
		string szShaderModel;
		ID3DBlob** blobOut=NULL;
		AuxUnGroupArgus(msg.p,szFileName,szEntryPoint,szShaderModel,blobOut);
		CompileShaderFromFile(szFileName,szEntryPoint,szShaderModel,blobOut);
		
	}
	catch(std::exception& e)
	{
		PRINT_ERROR(e)
	}
}
